package com.dz.lm.service.userorder.impl;

import com.dz.lm.common.dto.PageDto;
import com.dz.lm.common.dto.UserApplyDTO;
import com.dz.lm.common.dto.UserOrderDTO;
import com.dz.lm.common.exception.ServiceException;
import com.dz.lm.common.util.DzCache;
import com.dz.lm.common.util.StringUtil;
import com.dz.lm.common.utils.DateUtil;
import com.dz.lm.dao.account.write.AccountDao;
import com.dz.lm.dao.order.write.OrderDao;
import com.dz.lm.dao.userapply.write.UserApplyDao;
import com.dz.lm.dao.userorder.read.UserOrderDao;
import com.dz.lm.domain.order.Order;
import com.dz.lm.domain.userapply.UserApply;
import com.dz.lm.domain.userorder.UserOrder;
import com.dz.lm.domain.userorder.UserOrderExample;
import com.dz.lm.service.userapply.UserApplyService;
import com.dz.lm.service.userorder.UserOrderService;
import com.dz.lm.service.userorderlog.UserOrderLogService;
import com.fasterxml.jackson.databind.util.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;

@Service
public class UserOrderServiceImpl implements UserOrderService {
    @Resource(name = "readUserOrderDao")
    private UserOrderDao readUserOrderDao;

    @Resource(name = "writeUserOrderDao")
    private com.dz.lm.dao.userorder.write.UserOrderDao writeUserOrderDao;
    @Autowired
    private UserOrderLogService userOrderLogService;
    @Autowired
    private UserApplyService userApplyService;
    @Resource
    private com.dz.lm.dao.account.read.AccountDao readAccountDao;
    @Resource
    private OrderDao writeOrderDao;
    @Resource
    private AccountDao writeAccountDao;
    @Resource(name = "writeUserApplyDao")
    private UserApplyDao  writeUserApplyDao;
    @Transactional
    @Override
    public String add(int appyId, int status, double price, int clientId, int businessId, String remark) throws ServiceException {
        UUID uuid = UUID.randomUUID();
        UserOrder order = new UserOrder();
        order.setOrderId(uuid.toString());
        order.setApplyId(appyId);
        order.setStatus(status);
        order.setPrice(new BigDecimal(price));
        order.setClientId(clientId);
        order.setBusinessId(businessId);
        order.setRemark(remark);
        order.setCreateTime(DateUtil.getTimeStr(new Date()));
        int i = writeUserOrderDao.insertSelective(order);
        if(i > 0){
            userOrderLogService.add(uuid.toString(),appyId,0+"",clientId);
        }
        return order.getOrderId();
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(String orderId, int applyId, int status, String loginsticId ,String remark , int uid) throws Exception  {
        int ret =0;
        UserOrder userOrder = null;
        if(!StringUtil.containEmpty(orderId)){
             userOrder = readUserOrderDao.selectByPrimaryKey(orderId);

        }else if(applyId >0){
            userOrder= readUserOrderDao.selectByApplyId(applyId);
        }
        UserOrder order = new UserOrder();
        if(!StringUtil.containEmpty(orderId)){
            order.setOrderId(orderId);
        }
        if(applyId > 0){
            order.setApplyId(applyId);
        }
        if(status > -1){
            order.setStatus(status);
        }
        if(!StringUtil.containEmpty(loginsticId)){
            order.setLogisticId(loginsticId);
        }
        if(!StringUtil.containEmpty(remark)){
            order.setRemark(remark);
        }
        order.setUpdateTime(DateUtil.getTimeStr(new Date()));
        UserApply apply = new UserApply();
        apply.setApplyId(userOrder.getApplyId());
        switch (status){
            case 1:
            case 4:
                apply.setHandleDto(1);
                writeUserApplyDao.updateByPrimaryKeySelective(apply);
                break;
            case 3:
            case 5:
            case 6:
                apply.setApplyDto(1);
                writeUserApplyDao.updateByPrimaryKeySelective(apply);
                break;
        }
        ret = writeUserOrderDao.updateByPrimaryKeySelective(order);
        if(ret > 0 && status > 0){ //交易成功
                userOrderLogService.add(orderId,userOrder.getApplyId(),status+"",uid);
            if(status == 3 || status ==1 || status ==5){ //交易成功 向商家支付 添加订单流水 ,或者交易失败
                    addPayOrder(userOrder, status);

            }
        }
        return ret;
    }
    @Transactional
    @Override
    public void addPayOrder( UserOrder userOrder ,int status) throws Exception{
        Order order = new Order();
        Map userInfo = new HashMap();
        UserApplyDTO apply = userApplyService.get(userOrder.getApplyId(), false);
        //商家账户
        userInfo.put("userId", userOrder.getBusinessId());
        Map<String, Object> Uaccount = readAccountDao.qryAccountInfoByUserId(userInfo);
        userInfo.clear();
        //客户账户
        userInfo.put("userId", userOrder.getClientId());
        Map<String, Object> Saccount = readAccountDao.qryAccountInfoByUserId(userInfo);
    switch (status){
        case 3: //交易成功
            //计算商家人的账户金额
            BigDecimal CostB = new BigDecimal(userOrder.getPrice().toString());
            BigDecimal amount = new BigDecimal(Uaccount.get("amount").toString());
            //判断是否进行 计算返点
            if(apply.getAgentUid() > 0 && apply.getRePoint() >0){
                BigDecimal repoint = new BigDecimal(apply.getRealPrice() / 100);
                //返点金额
                BigDecimal  returnPoint = CostB.multiply(repoint);
                CostB =CostB.subtract(returnPoint);
                //代理人账户信息
                userInfo.clear();
                userInfo.put("userId",apply.getAgentUid());
                Map<String, Object> agentCount = readAccountDao.qryAccountInfoByUserId(userInfo);
                BigDecimal agamount = new BigDecimal(Uaccount.get("amount").toString());
                BigDecimal agnowAmount = agamount.add(repoint);
                BigDecimal agcashAmount = new BigDecimal(Uaccount.get("cashAmount").toString());
                BigDecimal nowagCashAmount = agcashAmount.add(repoint);
                order.setOrderId(getOrderId());
                order.setUserId(Integer.parseInt(agentCount.get("userId").toString()));
                order.setAccountId(Integer.valueOf(agentCount.get("accountId").toString()));
                order.setAmount(returnPoint.doubleValue());
                order.setGatherAccountId(Integer.valueOf(agentCount.get("accountId").toString()));
                order.setGatherUserId(Integer.parseInt(agentCount.get("userId").toString()));
                order.setOrderType("7");//返点 -收入
                order.setPayType("3");//账户
                order.setState("13");//冲入
                writeOrderDao.addOrder(order);
                order.setOrderId(getOrderId());
                order.setUserId(Integer.parseInt(Uaccount.get("userId").toString()));
                order.setAccountId(Integer.valueOf(Uaccount.get("accountId").toString()));
                order.setAmount(returnPoint.doubleValue());
                order.setGatherAccountId(Integer.valueOf(agentCount.get("accountId").toString()));
                order.setGatherUserId(Integer.parseInt(agentCount.get("userId").toString()));
                order.setOrderType("5");//返点 -支出
                order.setPayType("3");//账户
                order.setState("23");//冲入
                writeOrderDao.addOrder(order);
                //更新账户
                agentCount.put("amount", agnowAmount);
                agentCount.put("cash_amount", nowagCashAmount);
                writeAccountDao.updateAccount(agentCount);

            }
            BigDecimal nowAmount = amount.add(CostB);
            BigDecimal cashAmount = new BigDecimal(Uaccount.get("cashAmount").toString());
            BigDecimal nowCashAmount = cashAmount.add(CostB);
            //代理人账户流水
            order.setOrderId(getOrderId());
            order.setUserId(Integer.parseInt(Uaccount.get("userId").toString()));
            order.setAccountId(Integer.valueOf(Uaccount.get("accountId").toString()));
            order.setAmount(userOrder.getPrice().doubleValue());
            order.setGatherAccountId(Integer.valueOf(Saccount.get("accountId").toString()));
            order.setGatherUserId(Integer.parseInt(Saccount.get("userId").toString()));
            order.setOrderType("10");//申请的订单 -收入
            order.setPayType("3");//账户
            order.setState("13");//冲入
            writeOrderDao.addOrder(order);

            //更新账户
            Uaccount.put("amount", nowAmount);
            Uaccount.put("cash_amount", nowCashAmount);
            writeAccountDao.updateAccount(Uaccount);
            break;
        case 1:
        case 5: //交易失败
            BigDecimal CostB1 = new BigDecimal(userOrder.getPrice().toString());
            BigDecimal agamount = new BigDecimal(Saccount.get("amount").toString());
            BigDecimal agnowAmount = agamount.add(CostB1);
            BigDecimal agcashAmount = new BigDecimal(Saccount.get("cashAmount").toString());
            BigDecimal nowagCashAmount = agcashAmount.add(CostB1);
            order.setOrderId(getOrderId());
            order.setUserId(Integer.parseInt(Uaccount.get("userId").toString()));
            order.setAccountId(Integer.valueOf(Uaccount.get("accountId").toString()));
            order.setAmount(userOrder.getPrice().doubleValue());
            order.setGatherAccountId(Integer.valueOf(Saccount.get("accountId").toString()));
            order.setGatherUserId(apply.getProductId());
            order.setOrderType("11");//申请的退款 -收入
            order.setPayType("3");//账户
            order.setState("13");//冲入
            writeOrderDao.addOrder(order);
            //更新账户
            Saccount.put("amount", agnowAmount);
            Saccount.put("cash_amount", nowagCashAmount);
            writeAccountDao.updateAccount(Saccount);
            break;
    }


    }
    /**
     * 生产订单ID
     */
    private String getOrderId() {
        String orderId = "";
        @SuppressWarnings("unchecked")
        List<String> orderIdList = (List<String>) DzCache.getCacheCode("orderId");
        if (orderIdList != null && orderIdList.get(0) != null) {
            orderId = orderIdList.get(0);
            orderIdList.remove(0);
        } else {
            long todayMaxorderId = DzCache.getCacheCode("todayMaxorderId") == null ? 0l : (long) DzCache.getCacheCode("todayMaxorderId");
            long maxId = todayMaxorderId + 100;
            DzCache.setCacheCode("todayMaxorderId", maxId);
            orderIdList = new ArrayList<String>();
            String strTime = DateUtil.getTimeStrFormat(new Date());
            String suffix = "00000000";
            for (long i = todayMaxorderId + 1; i < maxId + 1; i++) {
                suffix = suffix + "" + i;
                suffix = suffix.substring(suffix.length() - 8, suffix.length());
                orderIdList.add(strTime + "" + suffix);
            }
            orderId = orderIdList.get(0);
            orderIdList.remove(0);
            DzCache.setCacheCode("orderId", orderIdList);
        }
        return orderId;
    }

    @Override
    public UserOrderDTO get(int applyId) throws ServiceException {
        UserOrderDTO dt = null;
        UserOrderExample ex = new UserOrderExample();
        UserOrderExample.Criteria cr = ex.createCriteria();
        cr.andApplyIdEqualTo(applyId);
        List<UserOrder> userOrders = readUserOrderDao.selectByExample(ex);
        if(userOrders != null && userOrders.size() > 0){
            dt = new UserOrderDTO();
            BeanUtils.copyProperties(userOrders.get(0),dt);
            try {
                setExt(dt,0);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return dt;
    }

    @Override
    public PageDto query(int pageNum  , int rows ,int businessId) throws ServiceException {
        PageHelper.startPage(pageNum,rows);
        PageDto pageDto = new PageDto();
        UserOrderExample ex = new UserOrderExample();
        UserOrderExample.Criteria cxr = ex.createCriteria();
        cxr.andBusinessIdEqualTo(businessId);
        List<UserOrder> userOrders = readUserOrderDao.selectByExample(ex);
        if(userOrders != null && userOrders.size() >0){
            List<UserOrderDTO> dtos = new ArrayList();
            PageInfo pageInfo=new PageInfo(userOrders);
            for (UserOrder order : userOrders) {
                UserOrderDTO dto = new UserOrderDTO();
                BeanUtils.copyProperties(order,dto);
                try {
                    setExt(dto,businessId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                dtos.add(dto);
            }
            pageDto.setList(dtos);
            pageDto.setInfo(pageInfo);
        }
        return pageDto;
    }
    private void setExt(UserOrderDTO dto , int businessId )throws Exception{
        UserApplyDTO applyDTO = userApplyService.get(dto.getApplyId(),false);
        if(applyDTO != null){
            Map subUser = (Map) applyDTO.getSubUser();
            Map supUser = (Map) applyDTO.getSupUser();
            Map product= (Map) applyDTO.getProduct();
            dto.setProductName(product.get("productName").toString());
            dto.setBusinessName(supUser.get("loginName").toString());
            dto.setClientName(subUser.get("loginName").toString());
            if(applyDTO.getAgentUser() != null){
                Map agentUser = (Map) applyDTO.getAgentUser();
                dto.setAgentName(agentUser.get("loginName").toString());
                dto.setOrginPrice(product.get("price").toString());
            }
            //  卖家填充返点信息
            if( businessId >0 && applyDTO.getAgentUid() > 0 && StringUtil.getDouble(product.get("returnPoint").toString(),0) >0){
                dto.setReturnPoint(new BigDecimal(product.get("returnPoint").toString()).multiply(new BigDecimal(dto.getPrice().toString())).setScale(2).toString());
            }
        }
        if(!StringUtil.containEmpty(dto.getUpdateTime())){
            Date d1 = com.smartlbs.util.DateUtil.getDateString2Date(dto.getUpdateTime());
            Calendar i1 = Calendar.getInstance();
            i1.setTime(d1);
            i1.add(Calendar.DAY_OF_YEAR,15);
            Calendar i2 = Calendar.getInstance();
            i2.setTime(new Date());
            int day1 = i1.get(Calendar.DAY_OF_YEAR);
            int day2 = i2.get(Calendar.DAY_OF_YEAR);
            dto.setDay(day1-day2);
        }
    }
    @Override
    public Map dealInfo(int businessId) throws ServiceException {
        return readUserOrderDao.getDealInfo(businessId);
    }
}
